﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;

using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Threading;

using Microsoft.WindowsAPICodePack.Dialogs;

namespace MakeReport
{
    public partial class Form_Main : Form
    {
        string xml_FilePath = "";//用来记录当前打开文件的路径的

        public Form_Main()
        {
            InitializeComponent();

            //new ConsoleHelper(textBox1);//重写Console的Write与WriteLine

            textBox_xml_path.Text = Properties.Settings.Default.xmlpath;
            xml_FilePath = Properties.Settings.Default.xmlpath;

            if (Properties.Settings.Default.xmlpath != "")
            {
                FillDataGrid(Properties.Settings.Default.xmlpath);
            }

            // 加载python.exe路径
            textBox_python_exe_path.Text = Properties.Settings.Default.pyExePath;

            // 加载输出文件夹路径
            textBox_output_folder.Text = Properties.Settings.Default.outputPath;

        }

        private void FillDataGrid(string xml_FilePath)
        {
            XmlDocument xmlDocument = new XmlDocument();//新建一个XML“编辑器”
            xmlDocument.Load(xml_FilePath);//载入路径这个xml
            try
            {
                XmlNodeList xmlNodeList = xmlDocument.SelectSingleNode("class").ChildNodes;//选择class为根结点并得到旗下所有子节点
                dataGridView1.Rows.Clear();//清空dataGridView1，防止和上次处理的数据混乱
                foreach (XmlNode xmlNode in xmlNodeList)//遍历class的所有节点
                {
                    XmlElement xmlElement = (XmlElement)xmlNode;//对于任何一个元素，其实就是每一个<student>
                                                                //旗下的子节点<name>和<number>分别放入dataGridView1
                    int index = dataGridView1.Rows.Add();//在dataGridView1新加一行，并拿到改行的行标
                    dataGridView1.Rows[index].Cells[0].Value = xmlElement.ChildNodes.Item(0).InnerText;//各个单元格分别添加
                    dataGridView1.Rows[index].Cells[1].Value = xmlElement.ChildNodes.Item(1).InnerText;
                    dataGridView1.Rows[index].Cells[2].Value = xmlElement.ChildNodes.Item(2).InnerText;
                }
            }
            catch
            {
                MessageBox.Show("XML格式不对！");
            }
        }

        private void button_read_xml_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new System.Windows.Forms.OpenFileDialog();//一个打开文件的对话框
            openFileDialog1.Filter = "xml文件(*.xml)|*.xml";//设置允许打开的扩展名
            if (openFileDialog1.ShowDialog() == DialogResult.OK)//判断是否选择了文件  
            {
                xml_FilePath = openFileDialog1.FileName;//记录用户选择的文件路径

                // 把xml文件路径写入配置
                Properties.Settings.Default.xmlpath = xml_FilePath;
                
                textBox_xml_path.Text = xml_FilePath;

                FillDataGrid(xml_FilePath);
            }
            else
            {
                MessageBox.Show("请打开XML文件");
            }

            //dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnMode.AllCells);
        }

        private void button_write_xml_Click(object sender, EventArgs e)
        {
            XmlDocument xmlDocument = new XmlDocument();//新建一个XML“编辑器”
            if (xml_FilePath != "")//如果用户已读入xml文件，我们的任务就是修改这个xml文件了
            {
                xmlDocument.Load(xml_FilePath);
                XmlNode xmlElement_class = xmlDocument.SelectSingleNode("class");//找到<class>作为根节点
                xmlElement_class.RemoveAll();//删除旗下所有节点
                int row = dataGridView1.Rows.Count;//得到总行数    
                int cell = dataGridView1.Rows[1].Cells.Count;//得到总列数    
                for (int i = 0; i < row - 1; i++)//遍历这个dataGridView
                {
                    XmlElement xmlElement_student = xmlDocument.CreateElement("student");//创建一个<student>节点

                    XmlElement xmlElement_name = xmlDocument.CreateElement("name");//创建<name>节点
                    xmlElement_name.InnerText = dataGridView1.Rows[i].Cells[0].Value.ToString();//其文本就是第0个单元格的内容
                    xmlElement_student.AppendChild(xmlElement_name);//在<student>下面添加一个新的节点<name>
                    
                    //同理添加<number>
                    XmlElement xmlElement_number = xmlDocument.CreateElement("number");
                    xmlElement_number.InnerText = dataGridView1.Rows[i].Cells[1].Value.ToString();
                    xmlElement_student.AppendChild(xmlElement_number);

                    XmlElement xmlElement_script = xmlDocument.CreateElement("script");
                    xmlElement_script.InnerText = dataGridView1.Rows[i].Cells[2].Value.ToString();
                    xmlElement_student.AppendChild(xmlElement_script);

                    xmlElement_class.AppendChild(xmlElement_student);//将这个<student>节点放到<class>下方
                }
                xmlDocument.Save(xml_FilePath);//保存这个xml
            }
            else//如果用户未读入xml文件，我们的任务就新建一个xml文件了
            {
                SaveFileDialog saveFileDialog1 = new System.Windows.Forms.SaveFileDialog();//打开一个保存对话框
                saveFileDialog1.Filter = "xml文件(*.xml)|*.xml";//设置允许打开的扩展名
                if (saveFileDialog1.ShowDialog() == DialogResult.OK)//判断是否选择了一个文件路径
                {
                    XmlElement xmlElement_class = xmlDocument.CreateElement("class");//创建一个<class>节点
                    int row = dataGridView1.Rows.Count;//得到总行数    
                    //int cell = dataGridView1.Rows[1].Cells.Count;//得到总列数    
                    for (int i = 0; i < row - 1; i++)//得到总行数并在之内循环    
                    {
                        //同上，创建一个个<student>节点，并且附到<class>之下
                        XmlElement xmlElement_student = xmlDocument.CreateElement("student");

                        XmlElement xmlElement_name = xmlDocument.CreateElement("name");
                        xmlElement_name.InnerText = dataGridView1.Rows[i].Cells[0].Value.ToString();
                        xmlElement_student.AppendChild(xmlElement_name);

                        XmlElement xmlElement_number = xmlDocument.CreateElement("number");
                        xmlElement_number.InnerText = dataGridView1.Rows[i].Cells[1].Value.ToString();
                        xmlElement_student.AppendChild(xmlElement_number);

                        XmlElement xmlElement_script = xmlDocument.CreateElement("scrpt");
                        xmlElement_script.InnerText = dataGridView1.Rows[i].Cells[2].Value.ToString();
                        xmlElement_student.AppendChild(xmlElement_script);

                        xmlElement_class.AppendChild(xmlElement_student);
                    }
                    xmlDocument.AppendChild(xmlDocument.CreateXmlDeclaration("1.0", "utf-8", ""));//编写文件头
                    xmlDocument.AppendChild(xmlElement_class);//将这个<class>附到总文件头，而且设置为根结点
                    xmlDocument.Save(saveFileDialog1.FileName);//保存这个xml文件
                }
                else
                {
                    MessageBox.Show("请保存为XML文件");
                }
            }

            
        }

        private void button_set_default_xml_Click(object sender, EventArgs e)
        {
            Properties.Settings.Default.xmlpath = textBox_xml_path.Text;
            Properties.Settings.Default.Save();
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void dataGridView1_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Link;
        }

        private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            // https://stackoverflow.com/questions/3577297/how-to-handle-click-event-in-button-column-in-datagridview

            var senderGrid = (DataGridView)sender;

            if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn &&
                e.RowIndex >= 0)
            {
                string pyPath = textBox_python_exe_path.Text;
                string pyFile = dataGridView1.Rows[e.RowIndex].Cells[2].Value.ToString();
                string inputFile = dataGridView1.Rows[e.RowIndex].Cells[1].Value.ToString();
                string outputFolder = textBox_output_folder.Text;
                DateTime start = dateTimePicker_start.Value;
                DateTime end = dateTimePicker_end.Value;
                //string[] additionArgs = { "arg1", "arg2", "arg3" };

                Call_python(pyPath, pyFile, inputFile, outputFolder, start, end);
            }
        }

        private void dataGridView1_DragDrop(object sender, DragEventArgs e)
        {
            if (!e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                return;
            }
            var path = e.Data.GetData(DataFormats.FileDrop) as string[];
            if (path != null && path.Length > 0)
            {
                var f = path[0];
                if (!string.IsNullOrEmpty(f))
                {
                    MessageBox.Show(f);

                    dataGridView1.CurrentCell.Value = f;
                }
            }

        }

        private void button1_Click(object sender, EventArgs e)
        {

        }

        private void button_this_month_Click(object sender, EventArgs e)
        {
            DateTime dt = DateTime.Now;
            DateTime startMonth = dt.AddDays(1 - dt.Day);  //本月月初
            DateTime endMonth = startMonth.AddMonths(1).AddDays(-1);  //本月月末/

            dateTimePicker_start.Value = startMonth;
            dateTimePicker_end.Value = endMonth;
        }

        private void button_last_month_Click(object sender, EventArgs e)
        {
            DateTime dt = DateTime.Now;
            DateTime startMonth = dt.AddDays(1 - dt.Day);  //本月月初

            DateTime lastMonthStart = startMonth.AddMonths(-1);  //上月月初/
            DateTime lastMonthEnd = dt.AddDays(1 - dt.Day).AddDays(-1);  //上月月末

            dateTimePicker_start.Value = lastMonthStart;
            dateTimePicker_end.Value = lastMonthEnd;
        }

        private void button_this_year_Click(object sender, EventArgs e)
        {
            DateTime dt = DateTime.Now;  //当前时间
            DateTime startYear = new DateTime(dt.Year, 1, 1);  //本年年初
            DateTime endYear = new DateTime(dt.Year, 12, 31);  //本年年末至于昨天、明天、上周、上月、上季度、上年度等等，

            dateTimePicker_start.Value = startYear;
            dateTimePicker_end.Value = endYear;
        }

        private void button_last_year_Click(object sender, EventArgs e)
        {
            DateTime dt = DateTime.Now;  //当前时间
            DateTime startYear = new DateTime(dt.Year, 1, 1);  //本年年初
            DateTime endYear = new DateTime(dt.Year, 12, 31);  //本年年末至于昨天、明天、上周、上月、上季度、上年度等等，

            dateTimePicker_start.Value = startYear.AddYears(-1);
            dateTimePicker_end.Value = endYear.AddYears(-1);
        }

        private void button_goto_today_Click(object sender, EventArgs e)
        {
            DateTime dt = DateTime.Now;  //当前时间
           
            dateTimePicker_start.Value = dt;
            dateTimePicker_end.Value = dt;
        }

        private void Call_python(string pyPath, string pyFile, string inputFile, string outputFolder, DateTime whenStart, DateTime whenEnd, string optArg1 = "", string optArg2 = "", string optArg3 = "", string optArg4 = "", string optArg5 = "" )
        {
            //https://www.jb51.net/article/177176.htm
            Console.WriteLine("Call_python args:");
            Console.WriteLine(pyPath);
            Console.WriteLine(pyFile);
            Console.WriteLine(inputFile);
            Console.WriteLine(outputFolder);
            Console.WriteLine(whenStart);
            Console.WriteLine(whenEnd);
            Console.WriteLine(optArg1);
            Console.WriteLine(optArg2);
            Console.WriteLine(optArg3);
            Console.WriteLine(optArg4);
            Console.WriteLine(optArg5);
            Console.WriteLine("Call_python start:");

            Process p = new Process();
            string path = pyFile;//待处理python文件的路径，本例中放在debug文件夹下
            string sArguments = path;
            ArrayList arrayList = new ArrayList();
            /*arrayList.Add("com4");
            arrayList.Add(57600);
            arrayList.Add("password");*/
            //arrayList.Add()
            arrayList.Add(inputFile);
            arrayList.Add(outputFolder);
            arrayList.Add(whenStart.ToString("yyyy-MM-dd"));
            arrayList.Add(whenEnd.ToString("yyyy-MM-dd"));
            arrayList.Add(optArg1);
            arrayList.Add(optArg2);
            arrayList.Add(optArg3);
            arrayList.Add(optArg4);
            arrayList.Add(optArg5);

            foreach (var param in arrayList)//添加参数
            {
                sArguments += " " + param;
            }

            //MessageBox.Show(sArguments);
            Console.WriteLine("完整调用语句");
            Console.WriteLine(sArguments);

            //p.StartInfo.FileName = @"D:\Python2\python.exe"; //python2.7的安装路径
            //p.StartInfo.FileName = @"C:\Users\zt\AppData\Local\Programs\Python\Python38-32\python.exe"; //python2.7的安装路径
            p.StartInfo.FileName = @pyPath;
            p.StartInfo.Arguments = sArguments;//python命令的参数
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = true;
            p.Start();//启动进程

            //p.WaitForExit();
            string pyOutput = p.StandardOutput.ReadToEnd();
            Console.WriteLine(pyOutput);
            string pyError = p.StandardError.ReadToEnd();
            Console.WriteLine(pyError);

            Console.WriteLine("执行完毕！");

            //Console.ReadKey();
            Console.Read();
        }
        
        private List<string> Find_Python_Exe()
        {
            string sPath = Environment.GetEnvironmentVariable("path");
            //Console.WriteLine(sPath);

            string[] paths = sPath.Split(';');
            //string[] pythonPaths = { };
            string[] sa = { };
            List<string> pythonPaths = new List<string>(sa);

            foreach (string path in paths)
            {
                //Console.WriteLine(path);
                if (path.ToLower().Contains("python"))
                {
                    //pythonPaths[pythonPaths.Length] = path;

                    //Console.WriteLine("find a python path: ");

                    var files = Directory.GetFiles(path, "*.exe");

                    foreach (var file in files)
                    {
                        Console.WriteLine(file);
                        if (file.ToLower().Contains("python.exe"))
                        {
                            pythonPaths.Add(file);
                        }
                    }


                }
            }

            Console.WriteLine("python.exe found in:");
            foreach (string pythonPath in pythonPaths)
            {
                Console.WriteLine(pythonPath);
            }

            return pythonPaths;
        }

        private void _progressBarTest()
        {
            progressBar1.Maximum = 10;

            if (progressBar1.Value < progressBar1.Maximum)
            {
                Console.WriteLine(string.Format("pb value: {0}", progressBar1.Value));
                progressBar1.Value += 1;
                Console.WriteLine(string.Format("pb value: {0}", progressBar1.Value));

                if (progressBar1.Value >= progressBar1.Maximum)
                {
                    MessageBox.Show("导出完成");
                }
            }
        }

        private void button_export_all_Click(object sender, EventArgs e)
        {
            List<string> pyPaths = Find_Python_Exe();

            string pyFile = "reset_ipc.py";

            string[] args = { "a", "b" };

            //Call_python(pyPaths[0], pyFile, textBox_output_folder.Text, DateTime.Now, DateTime.Now, args);

            // _progressBarTest();




        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox1 ab = new AboutBox1();
            ab.Show();
        }

        private void helpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("https://gitee.com/YES-LCD-TOOLS/report-filter-tool");
        }

        private void wikiToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("https://gitee.com/YES-LCD-TOOLS/report-filter-tool/wikis");
        }

        private void button_open_python_exe_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new System.Windows.Forms.OpenFileDialog();//一个打开文件的对话框
            openFileDialog1.InitialDirectory = "";
            openFileDialog1.Filter = "exe文件(*.exe)|*.exe";//设置允许打开的扩展名
            if (openFileDialog1.ShowDialog() == DialogResult.OK)//判断是否选择了文件  
            {
                MessageBox.Show("find a exe file");
            }
        }

        private void button_find_python_exe_Click(object sender, EventArgs e)
        {
            List<string> pyExePaths = Find_Python_Exe();
            if(pyExePaths[0] != "")
            {
                textBox_python_exe_path.Text = pyExePaths[0];
            }
        }

        private void button_save_python_exe_Click(object sender, EventArgs e)
        {
            Properties.Settings.Default.pyExePath = textBox_python_exe_path.Text;
            Properties.Settings.Default.Save();
        }

        private void button_open_output_folder_Click(object sender, EventArgs e)
        {
            CommonOpenFileDialog dialog = new CommonOpenFileDialog();
            if(textBox_output_folder.Text != "")
            {
                dialog.InitialDirectory = textBox_output_folder.Text;
            } else
            {
                dialog.InitialDirectory = "C:\\Users";
            }
           
            dialog.IsFolderPicker = true;
            if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
            {
                //MessageBox.Show("You selected: " + dialog.FileName);
                textBox_output_folder.Text = dialog.FileName;
            }
        }

        private void button_set_output_folder_Click(object sender, EventArgs e)
        {
            Properties.Settings.Default.outputPath = textBox_output_folder.Text;
            Properties.Settings.Default.Save();
        }

        private void ToolStripMenuItem_setting_Click(object sender, EventArgs e)
        {
            SettingForm settingForm = new SettingForm();
            settingForm.Show();
        }

        private void button_open_ouput_folder_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start("Explorer.exe", textBox_output_folder.Text);
        }

        private void chartToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form_Show_Chart formShowChart = new Form_Show_Chart();
            formShowChart.Show();
        }
    }

    public class ConsoleHelper : TextWriter
    {
        // https://blog.csdn.net/sinat_34114070/article/details/78427164
        private System.Windows.Forms.TextBox _textBox { set; get; }
        private int maxRowLenght = 200;//textBox中显示的最大行数，若不限制，则置为0
        public ConsoleHelper(System.Windows.Forms.TextBox textBox)
        {
            this._textBox = textBox;
            Console.SetOut(this);
        }
        public override void Write(string value)
        {
            if (_textBox.IsHandleCreated)
                _textBox.BeginInvoke(new ThreadStart(() =>
                {
                    if (maxRowLenght > 0 && _textBox.Lines.Length > maxRowLenght)
                    {
                        int strat = _textBox.GetFirstCharIndexFromLine(0);//获取第0行第一个字符的索引
                        int end = _textBox.GetFirstCharIndexFromLine(10);
                        _textBox.Select(strat, end);//选择文本框中的文本范围
                        _textBox.SelectedText = "";//将当前选定的文本内容置为“”
                        _textBox.AppendText(value + " ");
                    }
                    else
                    {
                        _textBox.AppendText(value + " ");
                    }
                }));
        }

        public override void WriteLine(string value)
        {
            if (_textBox.IsHandleCreated)
                _textBox.BeginInvoke(new ThreadStart(() =>
                {
                    if (maxRowLenght > 0 && _textBox.Lines.Length > maxRowLenght)
                    {
                        int strat = _textBox.GetFirstCharIndexFromLine(0);//获取第0行第一个字符的索引
                        int end = _textBox.GetFirstCharIndexFromLine(10);
                        _textBox.Select(strat, end);//选择文本框中的文本范围
                        _textBox.SelectedText = "";//将当前选定的文本内容置为“”
                        _textBox.AppendText(value + "\r\n");
                    }
                    else
                    {
                        _textBox.AppendText(value + "\r\n");
                    }
                }));
        }

        public override Encoding Encoding//这里要注意,重写wirte必须也要重写编码类型
        {
            get { return Encoding.UTF8; }
        }
    }
}
